package com.quanyan.club.web.filter;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;

import com.alibaba.fastjson.JSON;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.ApiResponseEnum;
import com.quanyan.club.constants.ClubRedisConstants;
import com.quanyan.club.entity.db.TbChannelExample;
import com.quanyan.club.entity.db.TbChannelSellExample;
import com.quanyan.club.mapper.TbChannelMapper;
import com.quanyan.club.mapper.TbChannelSellMapper;
import com.quanyan.club.pullclub.utils.DES;
import com.quanyan.club.pullclub.utils.StringUtils;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.user.AppUserCacheInfo;
import com.quanyan.common.utils.HttpServletRequestWrapper;
import com.quanyan.common.utils.MD5Utils;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.redisCluster.config.RedisTemplate;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * @Author Hugo.Wwg
 * @Since 2016-06-02
 */
@Component
public class CommonFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(CommonFilter.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    private void ajaxError(ApiResponseEnum apiResponseEnum, ServletResponse response)
            throws IOException {
        response.getWriter().write(JSON.toJSON(APIResponse.returnFail(apiResponseEnum)).toString());
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        long startTime = System.currentTimeMillis();
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        String uri = request.getRequestURI();

        if (uri.startsWith("/api/club/callBack/")) {
            chain.doFilter(request, response);
            return;
        }

        String sign = request.getHeader("sign");
        String appVersion = request.getHeader("APPVersion");
        String sessionId = request.getHeader("userCookiesName");
        logger.warn("---- sign={}, APPVersion={}, sessionId={}", sign, appVersion, sessionId);

        if (!Strings.isNullOrEmpty(appVersion)) {
            request.setAttribute("appVersion", appVersion);
        }

//        if(Strings.isNullOrEmpty(sign)){
//            ajaxError(ApiResponseEnum.ILLEGAL_PROTOCOL, response);
//            return;
//        }

        ServletRequest requestWrapper = new HttpServletRequestWrapper(request);

        if (!uri.startsWith("/admin/api/club")) {
            String reqData = getBodyString(requestWrapper.getReader(), uri);
            logger.warn("CommonFilter读取body中的参数: " + reqData);
            if (reqData == null) {
                ajaxError(ApiResponseEnum.ILLEGAL_PROTOCOL, response);
                return;
            }
            String md5Sign = MD5Utils.MD5Encode(reqData + Constants.SECRET_KEY);
            if (!sign.equals(md5Sign)) {
                ajaxError(ApiResponseEnum.ILLEGAL_PROTOCOL, response);
                return;
            }
        }

        try {
            if (!checkPullClubUriAccess(uri,request)){//渠道经销商接口校验token
                return ;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        logger.warn("Request Start，Request URI: " + uri + "，sessionId: "
                + sessionId + "appVersion: " + appVersion);

        RedisKey redisKey = new RedisKey(sessionId, "");
        AppUserCacheInfo appUserCacheInfo = (AppUserCacheInfo)
                redisTemplate.getObjectFromC(redisKey, AppUserCacheInfo.class);

//        if (appUserCacheInfo == null) {
//            logger.warn("Request End，appUserCacheInfo为null，Request URI: "
//                    + request.getRequestURI() + "，Time spent: "
//                    + (System.currentTimeMillis() - startTime) + "ms");
//            ajaxError(ApiResponseEnum.ILLEGAL_PROTOCOL, response);
//            return;
//        }

        if (appUserCacheInfo != null) {
            Integer uid = appUserCacheInfo.getUser_id();
            if (uid != null && uid != 0) {
                request.setAttribute("uid", uid); //uid不为null表示已经登录, 为0表示为游客身份
            }
        }

        chain.doFilter(requestWrapper, response);

        logger.warn("Request End，Request URI: " + request.getRequestURI()
                + "，Time spent: " + (System.currentTimeMillis() - startTime) + "ms");
    }


    public static String getBodyString(BufferedReader br, String reqUrl) {
        String inputLine;
        String str = "";
        try {
            while ((inputLine = br.readLine()) != null) {
                str += inputLine;
            }
            br.close();
        } catch (IOException e) {
            logger.warn("requestUrl: " + reqUrl + ", Request error: "
                    + e.getMessage() + "Request URI: ");

        }
        return str;
    }

    @Autowired
    private TbChannelMapper tbChannelMapper;

    @Autowired
    private TbChannelSellMapper tbChannelSellMapper;
    /**
     * 检查渠道分销商请求的token是否存在
     * @param uri
     * @param request
     * @return
     * @throws IOException
     */
    private  boolean checkPullClubUriAccess(String uri,HttpServletRequest request) throws Exception {
        logger.warn("-------checkPullClubUriAccess--------"+JSON.toJSONString(request.getHeaderNames()));
        if (uri.startsWith("/api/club/pullclub") && !uri.startsWith("/api/club/pullclub/pullClubRegister")
                && !uri.startsWith("/api/club/pullclub/getEncryptCode") && !uri.startsWith("/api/club/pullclub/myPullNewClubs") && !uri.startsWith("/api/club/pullclub/plQrCode")){
            String token=request.getHeader("token");
            String codes=request.getHeader("tokenCode");
            String mobile=request.getHeader("tokenMobile");
            String tokenChannel=request.getHeader("tokenChannel");
            logger.warn(token+"---checkPullClubUriAccess--"+codes+"----"+mobile+"------"+tokenChannel);
            if (StringUtils.isBlankOrNull(codes) || StringUtils.isBlankOrNull(token) || StringUtils.isBlankOrNull(mobile) || StringUtils.isBlankOrNull(tokenChannel)){
                return false;
            }
            if (!"QD".equals(tokenChannel) && !"FX".equals(tokenChannel)){
                return false;
            }
            Map<String, String> paramMap = new HashMap<>();
            String code = DES.decrypt(codes);
            String[] str = code.split("&");
            for (int i = 0; i < str.length; i++) {
                String[] msg = str[i].split("=");
                paramMap.put(msg[0], msg[1]);
            }
            logger.warn("paramMap-------"+JSON.toJSONString(paramMap));
            if (!paramMap.containsKey("type") || !paramMap.containsKey("code")) {
                throw new BizException(ApiResponseEnum.PARAMETER_INVALID);
            }
            if ("QD".equals(tokenChannel)){
                TbChannelExample tbChannelExample=new TbChannelExample();
                tbChannelExample.createCriteria().andSellCodeEqualTo(paramMap.get("code")).andChMobileEqualTo(mobile);
                int count=tbChannelMapper.countByExample(tbChannelExample);
                if (count<=0){
                    return false;
                }
            }else if ("FX".equals(tokenChannel)){
                TbChannelSellExample tbChannelSellExample=new TbChannelSellExample();
                tbChannelSellExample.createCriteria().andCodeEqualTo(paramMap.get("code")).andSellMobileEqualTo(mobile);
                int count=tbChannelSellMapper.countByExample(tbChannelSellExample);
                if (count<=0){
                    return false;
                }
            }
            String key = ClubRedisConstants.CLUB_CHANNEL_TOKEN+paramMap.get("code")+token;
            RedisKey redisKey = new RedisKey(RedisConstants.CLUB_FAMILY_KEY, key);
            if (redisTemplate.exists(redisKey)){
                return true;
            }
            return false;
        }
        return true;
    }
}
